#include "button.h"
#include "timer.h"
#include "system.h"
#include "render.h"
#include "animation.h"
#include "log.h"

#include <string.h>
#include <stdio.h>
#include <memory.h>
#include <stdlib.h>

#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xmlmemory.h>

#define ALPHA_TIME 500

typedef enum _UFO_BTN_STATE
{
	BTN_NORMAL,
	BTN_CLICKED,
	BTN_HOVER,
	BTN_DISABLE
}UFO_BTN_STATE;

typedef struct _BUTTON
{
	UFO_Texture normal, hover, touch;
	UFO_Timer timer;
	
	long tickCount;
	float alpha, beg_alpha;
	UFO_BTN_STATE state;
}BUTTON;

int ufoFlipViewFlip(UFO_View view);//#### yuedongweng's trick

int ufoButtonSetNormalImage(UFO_View view, UFO_Texture texture)
{
	BUTTON *pBotton = (BUTTON*)ufoViewGetUserData(view);
	if (pBotton) {
		pBotton->normal = texture;
		return 1;
	}
	return 0;
}

int ufoButtonSetHoverImage(UFO_View view, UFO_Texture texture)
{
	BUTTON *pBotton = (BUTTON*)ufoViewGetUserData(view);
	if (pBotton) {
		pBotton->hover = texture;
		return 1;
	}
	return 0;
}

int ufoButtonSetTouchedImage(UFO_View view, UFO_Texture texture)
{
	BUTTON *pBotton = (BUTTON*)ufoViewGetUserData(view);
	if (pBotton) {
		pBotton->touch = texture;
		return 1;
	}
	return 0;
}

int default_button_proc(UFO_View view, int id, void* wParam, void* lParam)
{
	BUTTON *pButton = (BUTTON*)ufoViewGetUserData(view);
	if (!pButton) {
		pButton = (BUTTON*)malloc(sizeof(BUTTON));
		memset(pButton, 0, sizeof(BUTTON));
		ufoViewSetUserData(view, pButton);
	}
	switch (id)
	{
	case MSG_TOUCH_DOWN:
		{
			pButton->state = BTN_CLICKED;
			ufoViewSetNeedPaint(view);
			if (pButton->timer) {
				ufoTimerDelete(pButton->timer);
				pButton->timer = 0;
			}
			pButton->alpha = 1.0f;
			//ufoViewSetCapture(view);

			//((UFO_TOUCH_STRUCT*)lParam)->bHandled = 1;//### not pass to parent view
		}
		break;

	case MSG_TOUCH_UP:
		{
			pButton->state = BTN_NORMAL;
			ufoViewSetNeedPaint(view);
			//ufoViewSetCapture(0);

			//((UFO_TOUCH_STRUCT*)lParam)->bHandled = 1;//### not pass to parent view
		}
		break;

	case MSG_TOUCH_ENTER:
		{
			if (pButton->timer)
				ufoTimerDelete(pButton->timer);
			pButton->timer = ufoTimerCreate(view, 0, -1, 0, 0);
			pButton->tickCount = ufoGetCurTime();
			pButton->state = BTN_HOVER;
			pButton->beg_alpha = pButton->alpha;
		}
		break;

	case MSG_TOUCH_LEAVE:
		{
			if (pButton->timer)
				ufoTimerDelete(pButton->timer);
			pButton->timer = ufoTimerCreate(view, 0, -1, 0, 0);
			pButton->tickCount = ufoGetCurTime();
			pButton->state = BTN_NORMAL;
			pButton->beg_alpha = pButton->alpha;
		}
		break;

	case MSG_TOUCH_CLICK:
		{
			//UFO_View view = ufoViewGetFromId(0, "flipView");
			//ufoFlipViewFlip(view);
		}
		break;

	case MSG_TOUCH_MOVE:
		{
			//((UFO_TOUCH_STRUCT*)lParam)->bHandled = 1;//### not pass to parent view
		}
		break;

	case MSG_XML:
		{
			ufoViewDefaultProc(view, id, wParam, lParam);

			{
				xmlNodePtr node = wParam;
				xmlChar *normalImage = xmlGetProp(node, (const xmlChar*)"normalImage");
				xmlChar *hoverImage = xmlGetProp(node, (const xmlChar*)"hoverImage");
				xmlChar *touchedImage = xmlGetProp(node, (const xmlChar*)"touchedImage");

				if (normalImage) {
					UFO_Texture tex = ufoResourceGetTexture((const char*)normalImage);
					ufoButtonSetNormalImage(view, tex);
					xmlFree(normalImage);
				}

				if (hoverImage) {
					UFO_Texture tex = ufoResourceGetTexture((const char*)hoverImage);
					ufoButtonSetHoverImage(view, tex);
					xmlFree(hoverImage);
				}

				if (touchedImage) {
					UFO_Texture tex = ufoResourceGetTexture((const char*)touchedImage);
					ufoButtonSetTouchedImage(view, tex);
					xmlFree(touchedImage);
				}
			}
		}
		return 1;

	case MSG_PAINT:
		{
			UFO_PAINT_STRUCT *paint = (UFO_PAINT_STRUCT*)lParam;
			ufoRect dst = {0};
			ufoViewGetRect(view, &dst);

			ufoViewDefaultProc(view, id, wParam, lParam);//### super 

			switch (pButton->state) {
			case BTN_NORMAL:
				{
					if (pButton->normal) {
						ufoTextureDraw(0, pButton->normal, 0, &dst, paint->stencilTest, paint->color, paint->alpha, 0.0f);
					}
				}
				break;
			case BTN_HOVER:
				{
					if (pButton->hover) {
						ufoTextureDraw(0, pButton->hover, 0, &dst, paint->stencilTest, paint->color, paint->alpha, 0.0f);
					}
				}
				break;

			case BTN_CLICKED:
				{
					if (pButton->touch) {
						ufoTextureDraw(0, pButton->touch, 0, &dst, paint->stencilTest, paint->color, paint->alpha, 0.0f);
					}
				}
				break;
                    
            default:
                {
                    
                }
                break;
			}
		}
		return 1;

	case MSG_TIMER:
		{
			long dt = ufoGetCurTime()-pButton->tickCount;
			int over = 0;
			
			if (pButton->state == BTN_HOVER) {
				if (dt > (long)(ALPHA_TIME*(1.0f-pButton->beg_alpha))) {
					dt = (long)(ALPHA_TIME*(1.0f-pButton->beg_alpha));
					over = 1;
				}
				pButton->alpha = (float)internal_calcInterpolation(TimingFunctionDefault, 
					pButton->beg_alpha, 1.0, ALPHA_TIME*(1.0f-pButton->beg_alpha), dt);
				
			}
			else {
				if (dt > ALPHA_TIME*(pButton->beg_alpha)) {
					dt = (long)(ALPHA_TIME*(pButton->beg_alpha));
					over = 1;
				}
				pButton->alpha = (float)internal_calcInterpolation(TimingFunctionDefault, 
					pButton->beg_alpha, 0.0, ALPHA_TIME*(pButton->beg_alpha), dt);	
			}

			if (over) {
				if (pButton->timer) {
					ufoTimerDelete(pButton->timer);
					pButton->timer = 0;
				}
			}
			ufoViewSetNeedPaint(view);
		}
		break;

	case MSG_CREATE:
		{
			BUTTON *pButton = (BUTTON*)malloc(sizeof(BUTTON));
			memset(pButton, 0, sizeof(BUTTON));
			ufoViewSetUserData(view, pButton);
		}
		break;
	}

	return ufoViewDefaultProc(view, id, wParam, lParam);//### pass to default view proc
}